package algoritmos;

import java.util.ArrayList;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JProgressBar;
import javax.swing.JTextArea;

import Jama.Matrix;

/**
 * Clase abstracta que definirá los distintos algoritmos numéricos presentados
 * en clase.
 * @author Alberto Milán
 *
 */
public abstract class AlgoritmoNumerico extends Algoritmo implements Runnable{
	/**
	 * Datos de entrada para el algoritmo.
	 * Siempre serán listas de listas de números enteros por el
	 * uso visto en clase, pero podrían ser de otro tipo numérico.
	 */
	protected ArrayList<Matrix> entrada;
	
	/**
	 * Dimensión de los datos.
	 */
	protected int dimension;
	
	/**
	 * Lista de los centros de las clases obtenidas.
	 */
	protected ArrayList<Matrix> centros;
	
	/**
	 * Listas de pertenencia de los datos de entrada
	 */
	protected ArrayList<Set<Integer>> conjuntos;
	
	/**
	 * Objetos gráficos que modificará
	 */
	protected JTextArea texto;
	protected JProgressBar progreso;
	protected JButton botonAprendizaje;
	protected JButton botonNuevoDato;
	protected JButton botonVisualizaGraficos;
	
	/**
	 * Constructor de la clase
	 */
	public AlgoritmoNumerico(){
		super();
		entrada = new ArrayList<Matrix>();
		centros = new ArrayList<Matrix>();
		dimension = 0;
		conjuntos = new ArrayList<Set<Integer>>();
	}
	
	/**
	 * Número de clases dispuestas por el algoritmo.
	 * @return Número de clases presentes en el algoritmos.
	 */
	public int numeroDeClases(){
		return centros.size();
	}
	
	/**
	 * Comprueba la convergencia de los centros en las distintas iteraciones.
	 * 
	 * @return El estado de convergencia del algoritmo.
	 */
	protected abstract boolean convergencia();	
	
	/**
	 * Calcula el grado de pertenencia a cada clase del problema.
	 * @param lista Dato de entrada.
	 * @return Lista de probabilidades o grados de pertenencia a cada clase.
	 */
	public abstract void perteneceAClase(ArrayList<Number> lista);
	
	/**
	 * Inicializa los componentes gráficos del aprendizaje
	 */
	protected void inicializaComponentesAprendizaje(){
		botonAprendizaje.setEnabled(false);
		if (botonVisualizaGraficos != null) botonVisualizaGraficos.setEnabled(false);
		botonNuevoDato.setEnabled(false);
		progreso.setIndeterminate(true);
	}
	
	/**
	 * Recompone los objetos gráficos del algoritmo
	 */
	protected void finalizaComponentesAprendizaje(){
		progreso.setIndeterminate(false);
		progreso.setValue(100);
		botonNuevoDato.setEnabled(true);
		if (botonVisualizaGraficos != null) botonVisualizaGraficos.setEnabled(true);
		botonAprendizaje.setEnabled(true);
	}
	
	/*=========================================================================*
	 *							Accesores y mutadores                          * 
	 *=========================================================================*/	

	public ArrayList<Matrix> getEntrada() {
		return entrada;
	}

	public void setEntrada(ArrayList<Matrix> entrada) {
		this.entrada = entrada;
	}

	public int getDimension() {
		return dimension;
	}

	public void setDimension(int dimension) {
		this.dimension = dimension;
	}

	public ArrayList<Matrix> getCentros() {
		return centros;
	}

	public void setCentros(ArrayList<Matrix> centros) {
		this.centros = centros;
	}

	public ArrayList<Set<Integer>> getConjuntos() {
		return conjuntos;
	}

	public void setConjuntos(ArrayList<Set<Integer>> conjuntos) {
		this.conjuntos = conjuntos;
	}

}
